home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Tools - Objects / MacApp / MacApp CD Release / MacApp 2.0.1 (Many Libraries) / Libraries / UTEView.TTEView.p < prev    next >
Encoding:
Text File  |  1990-10-25  |  50.0 KB  |  1,853 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { UTEView.TTEView.p }
  4. { Copyright © 1984-1990 Apple Computer Inc.  All rights reserved. }
  5.  
  6. {--------------------------------------------------------------------------------------------------}
  7. {$S TEOpen}
  8.  
  9. PROCEDURE TTEView.ITEView(itsDocument: TDocument;
  10.                           itsSuperView: TView;
  11.                           itsLocation, itsSize: VPoint;
  12.                           itsHDeterminer, itsVDeterminer: SizeDeterminer;
  13.                           itsInset: Rect;
  14.                           itsTextStyle: TextStyle;
  15.                           itsJustification: INTEGER;
  16.                           itsStyleType, itsAutoWrap: BOOLEAN);
  17.  
  18.     BEGIN
  19.     {$IFC qDebug}
  20.     IF NOT gUTEViewInitialized THEN
  21.         BEGIN
  22.         ProgramBreak('InitUTEView must be called before creating a TE View.');
  23.         Failure(noErr, 0);
  24.         END;
  25.     {$ENDC}
  26.  
  27.     {$IFC qDebug}
  28.     pTEIntenseDebugging := FALSE;
  29.     {$ENDC}
  30.  
  31.     fHTE := NIL;
  32.     fText := NIL;
  33.     fSavedTEHandle := NIL;
  34.     fInset := itsInset;
  35.     fKeyCmdNumber := cTyping;
  36.     fMaxChars := kUnlimited;
  37.     fLastHeight := 0;
  38.     fLastWidth := 0;
  39.     fTypingCommand := NIL;
  40.     fTextStyle := itsTextStyle;
  41.     fJustification := itsJustification;
  42.  
  43.     fAcceptsChanges := TRUE;                            { Stuff to FALSE if you don't want to allow
  44.                                                          Cut, Paste, or Typing }
  45.     {!!! put these in the template after 2.0 !!!}
  46.     fControlChars := [chLeft, chRight, chUp, chDown, chBackspace, chReturn];
  47.     fMinAhead := kMinAhead;
  48.  
  49.     fStyleType := (qNeedsStyleTextEdit | gConfiguration.hasStyleTextedit) & itsStyleType;
  50.     fAutoWrap := itsAutoWrap;
  51.     fFreeText := FALSE;
  52.     fSpecsChanged := FALSE;
  53.  
  54.     fLastPageBreak := 0;
  55.     fLastLine := 0;
  56.  
  57.     IView(itsDocument, itsSuperView, itsLocation, itsSize, itsHDeterminer, itsVDeterminer);
  58.  
  59.     MakeTERecord;
  60.  
  61.     SetClikLoop(@ClickLoopForTTEView, fHTE);                { fHTE^^.clikLoop := @ClickLoopForTTEView; }
  62.     { ??? Things don't work well if fText is non-NIL.  Is this the way to solve it? }
  63.     fText := fHTE^^.hText;
  64.  
  65.     SetIdleFreq(0);                                     { Idle ASAP }
  66.     END;
  67.  
  68. {--------------------------------------------------------------------------------------------------}
  69. {$S TEOpen}
  70.  
  71. PROCEDURE TTEView.IRes(itsDocument: TDocument;
  72.                        itsSuperView: TView;
  73.                        VAR itsParams: Ptr); OVERRIDE;
  74.  
  75.     VAR
  76.         aTextStyle:         TextStyle;
  77.  
  78.     BEGIN
  79.     {$IFC qDebug}
  80.     IF NOT gUTEViewInitialized THEN
  81.         BEGIN
  82.         ProgramBreak('InitUTEView must be called before creating a TE View.');
  83.         Failure(noErr, 0);
  84.         END;
  85.     {$ENDC}
  86.  
  87.     {$IFC qDebug}
  88.     pTEIntenseDebugging := FALSE;
  89.     {$ENDC}
  90.  
  91.     fHTE := NIL;                                        { In case of emergency. }
  92.     fText := NIL;
  93.     fSavedTEHandle := NIL;
  94.     fLastPageBreak := 0;
  95.     fLastLine := 0;
  96.  
  97.     {!!! put these in the template after 2.0 !!!}
  98.     fControlChars := [chLeft, chRight, chUp, chDown, chBackspace, chReturn];
  99.     fMinAhead := kMinAhead;
  100.  
  101.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  102.  
  103.     WITH TEViewTemplatePtr(itsParams)^ DO
  104.         BEGIN
  105.         fTypingCommand := NIL;
  106.         fLastHeight := 0;
  107.         fLastWidth := 0;
  108.         fSpecsChanged := FALSE;
  109.  
  110.         fInset := itsInset;
  111.         fKeyCmdNumber := itsKeyCmdNumber;
  112.         fMaxChars := itsMaxChars;
  113.         SetTextStyle(aTextStyle, GetFontNum(itsFontName), itsTextFace, itsTextSize, itsTextColor);
  114.         fTextStyle := aTextStyle;
  115.         fJustification := itsJustification;
  116.         fAcceptsChanges := itsAcceptsChanges;
  117.         fStyleType := (qNeedsStyleTextEdit | gConfiguration.hasStyleTextedit) & itsStyleType;
  118.         fAutoWrap := itsAutoWrap;
  119.         fFreeText := itsFreesText;
  120.  
  121.         MakeTERecord;
  122.  
  123.         SetClikLoop(@ClickLoopForTTEView, fHTE);        { fHTE^^.clikLoop := @ClickLoopForTTEView; }
  124.         fText := fHTE^^.hText;
  125.  
  126.         SetIdleFreq(0);                                 { Idle ASAP }
  127.         END;
  128.  
  129.     OffsetPtrWStr(itsParams, SIZEOF(TEViewTemplate));
  130.     END;
  131.  
  132. {--------------------------------------------------------------------------------------------------}
  133. {$S MAWriteRes}
  134.  
  135. PROCEDURE TTEView.WRes(theResource: ViewRsrcHndl;
  136.                        VAR itsParams: Ptr); OVERRIDE;
  137.  
  138.     VAR
  139.         theFont:            Str255;
  140.         ttPtr:                TEViewTemplatePtr;
  141.  
  142.     BEGIN
  143.     INHERITED WRes(theResource, itsParams);
  144.  
  145.     GetFontName(fTextStyle.tsFont, theFont);
  146.  
  147.     ttPtr := TEViewTemplatePtr(ExpandPtrWStr(theResource, itsParams, SIZEOF(TEViewTemplate),
  148.                                              LENGTH(theFont)));
  149.  
  150.     WITH ttPtr^ DO
  151.         BEGIN
  152.         itsStyleType := fStyleType;
  153.         itsAutoWrap := fAutoWrap;
  154.         itsAcceptsChanges := fAcceptsChanges;
  155.         itsFreesText := fFreeText;
  156.         itsKeyCmdNumber := fKeyCmdNumber;
  157.         itsMaxChars := fMaxChars;
  158.         itsInset := fInset;
  159.         itsJustification := fJustification;
  160.         WITH fTextStyle DO
  161.             BEGIN
  162.             itsTextFace := tsFace;
  163.             itsTextSize := tsSize;
  164.             itsTextColor := tsColor;
  165.             END;
  166.         { itsFontName := theFont; }
  167.         CopyStr255(theFont, PRStr(itsFontName));
  168.         END;
  169.     END;
  170.  
  171. {--------------------------------------------------------------------------------------------------}
  172. {$S MAWriteRes}
  173.  
  174. PROCEDURE TTEView.WriteRes(theResource: ViewRsrcHndl;
  175.                            VAR itsParams: Ptr); OVERRIDE;
  176.  
  177.     BEGIN
  178.     gWResSignature := 'tevw'; gWResType := 'TTEView';
  179.     WRes(theResource, itsParams);
  180.     END;
  181.  
  182. {--------------------------------------------------------------------------------------------------}
  183. {$S TEClose}
  184.  
  185. PROCEDURE TTEView.Free; OVERRIDE;
  186.  
  187.     BEGIN
  188.     IF fHTE <> NIL THEN
  189.         BEGIN
  190.         IF fSavedTEHandle <> NIL THEN
  191.             WITH fHTE^^ DO
  192.                 BEGIN                                    { Worry about fText separately. Put back }
  193.                 hText := fSavedTEHandle;                { …the handle which TE allocated }
  194.                 {$Push} {$H-}
  195.                 teLength :=                             { This is here because it only makes }
  196.                   GetHandleSize(hText);
  197.                 IF fFreeText THEN                        { …sense if fSavedTEHandle is not NIL. }
  198.                     fText := DisposeIfHandle(fText);
  199.                 fText := NIL;                            { Always drop my reference }
  200.                 {$Pop}
  201.                 END;
  202.         TEDispose(fHTE);
  203.         fHTE := NIL;
  204.  
  205.         fSavedTEHandle := NIL;
  206.         END;
  207.  
  208.     INHERITED Free;
  209.     END;
  210.  
  211. {--------------------------------------------------------------------------------------------------}
  212. {$S TENonRes}
  213.  
  214. FUNCTION TTEView.ClikLoop: BOOLEAN;
  215.  
  216.     VAR
  217.         msePt:                Point;
  218.         viewPt:             VPoint;
  219.         visRect:            Rect;
  220.         delta:                VPoint;
  221.         vhs:                VHSelect;
  222.         lead:                INTEGER;
  223.         trail:                INTEGER;
  224.         scroller:            TScroller;
  225.  
  226.     BEGIN
  227.     IF StillDown THEN
  228.         BEGIN
  229.         scroller := GetScroller(FALSE);
  230.         IF (scroller <> NIL) & scroller.Focus THEN
  231.             BEGIN
  232.             GetMouse(msePt);
  233.             scroller.QDToViewPt(msePt, viewPt);
  234.             scroller.AutoScroll(viewPt, delta);    { find how much should scroll }
  235.             IF Focus THEN
  236.                 BEGIN
  237.                 GetVisibleRect(visRect);
  238.     
  239.                 FOR vhs := v TO h DO
  240.                     BEGIN
  241.                     lead := fLocation.vh[vhs] - visRect.topLeft.vh[vhs];
  242.                     trail := fLocation.vh[vhs] + fSize.vh[vhs] - visRect.botRight.vh[vhs];
  243.     
  244.                     IF delta.vh[vhs] < 0 THEN
  245.                         delta.vh[vhs] := Min(MAX(delta.vh[vhs], lead), 0)
  246.                     ELSE
  247.                         delta.vh[vhs] := MAX(Min(delta.vh[vhs], trail), 0);
  248.                     END;
  249.                 { The intent of the above is not to do autoscrolling that would scroll
  250.                   beyond the subview boundary in any direction }
  251.     
  252.                 IF (delta.v <> 0) | (delta.h <> 0) THEN
  253.                     BEGIN
  254.                     scroller.ScrollBy(delta.h, delta.v, kRedraw);
  255.                     Update;    { make sure the scrolling was visible }
  256.                     END;
  257.                 END;
  258.             END;
  259.         
  260.         {!!! need an IsCursorRgnValid method }
  261.         IF EmptyRgn(gCursorRgn) & gApplication.TrackCursor THEN;
  262.  
  263.         { Focus may have changed, which could change lots of things, thus
  264.         requiring us, tiresomely, to take some or all of the following
  265.         restorative precautions b/c clikloop expects us to be clipped to the
  266.         destrect. }
  267.         IF Focus THEN
  268.             ClipFurtherTo(fHTE^^.destRect, 0, 0);
  269.         END;
  270.     ClikLoop := TRUE;                                    { Still consider the mouse to be down }
  271.     END;
  272.  
  273. {--------------------------------------------------------------------------------------------------}
  274. {$S TENonRes}
  275.  
  276. PROCEDURE TTEView.AutoScrolling(doScrolling: BOOLEAN);
  277.  
  278.     BEGIN
  279.     IF qNeedsROM128K | gConfiguration.hasROM128K THEN
  280.         IF fHTE <> NIL THEN
  281.             TEAutoView(doScrolling, fHTE);
  282.     END;
  283.  
  284. {--------------------------------------------------------------------------------------------------}
  285. {$S TENonRes}
  286.  
  287. PROCEDURE TTEView.BeInPort(itsPort: GrafPtr); OVERRIDE;
  288.  
  289.     BEGIN
  290.  
  291.     IF fHTE <> NIL THEN
  292.         BEGIN
  293.         WITH fHTE^^ DO
  294.             IF itsPort = NIL THEN
  295.                 inPort := gWorkPort
  296.             ELSE
  297.                 inPort := itsPort;
  298.  
  299.         IF itsPort = NIL THEN
  300.             BEGIN
  301.             DoneTyping;
  302.             fSpecsChanged := TRUE;
  303.             END;
  304.         END;
  305.  
  306.     INHERITED BeInPort(itsPort);
  307.     END;
  308.  
  309. {--------------------------------------------------------------------------------------------------}
  310. {$S TENonRes}
  311.  
  312. PROCEDURE TTEView.BeInScroller(itsScroller: TScroller); OVERRIDE;
  313.  
  314.     VAR
  315.         vertScrollUnit:     INTEGER;
  316.  
  317.     BEGIN
  318.     IF (fHTE <> NIL) & (itsScroller <> NIL) THEN
  319.         BEGIN
  320.         IF fHTE^^.lineHeight > 0 THEN                    { This works for both old & new TextEdit }
  321.             vertScrollUnit := fHTE^^.lineHeight
  322.         ELSE IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN { Ask for system default
  323.                     size }
  324.             vertScrollUnit := GetDefFontSize
  325.         ELSE
  326.             vertScrollUnit := kStdScrollUnit;
  327.  
  328.         itsScroller.SetScrollParameters(kStdScrollUnit, vertScrollUnit, FALSE, TRUE);
  329.         END;
  330.  
  331.     INHERITED BeInScroller(itsScroller);
  332.     END;
  333.  
  334. {--------------------------------------------------------------------------------------------------}
  335. {$S TENonRes}
  336.  
  337. PROCEDURE TTEView.CalcMinSize(VAR minSize: VPoint); OVERRIDE;
  338.  
  339.     BEGIN
  340.  { Note that we omit the margins here, so that if TView.ComputeExtent rounds up to a
  341.    page multiple, the margins will get tacked on after.  Also, insure we don't run off
  342.    the end of the coordinate system if there are many lines of text. }
  343.  
  344.     SetVPt(minSize, fSize.h - fInset.left - fInset.right, Min(kMaxCoord, CalcRealHeight));
  345.  
  346.     IF (fSizeDeterminer[h] = sizeVariable) & NOT fStyleType & NOT fAutoWrap THEN
  347.         SetVPt(minSize, fLastWidth, minSize.v);
  348.  
  349.     END;
  350.  
  351. {--------------------------------------------------------------------------------------------------}
  352. {$S TERes}
  353.  
  354. FUNCTION TTEView.CalcRealHeight: LONGINT;
  355.  
  356.     VAR
  357.         lastIsCR:            BOOLEAN;
  358.         theMode:            INTEGER;
  359.         theHeight:            LONGINT;
  360.         theStyle:            TextStyle;
  361.         theFontInfo:        FontInfo;
  362.  
  363.     BEGIN
  364.     {$Push} {$R-}
  365.     WITH fHTE^^ DO
  366.         lastIsCR := (teLength <= 0) | (CharsHandle(hText)^^[PRED(teLength)] = chReturn);
  367.     {$Pop}
  368.  
  369.     IF fStyleType = kWithStyle THEN
  370.         BEGIN
  371.         theHeight := 0;
  372.         IF fHTE^^.nLines > 0 THEN
  373.             theHeight := TEGetHeight(MAXINT, 0, fHTE);
  374.  
  375.         IF lastIsCR THEN                                { then can't use TEGetHeight so we }
  376.             BEGIN                                        { …have to figure it out ourselves. }
  377.             theMode := doAll;
  378.             lastIsCR := ContinuousStyle(MAXINT, MAXINT, theMode, theStyle);
  379.  
  380.             GetTextStyleFontInfo(theStyle, theFontInfo);
  381.  
  382.             WITH theFontInfo DO
  383.                 theHeight := theHeight + ascent + descent + leading;
  384.             END;
  385.         END
  386.     ELSE
  387.         BEGIN
  388.         theHeight := fHTE^^.nLines + ORD(lastIsCR);
  389.         theHeight := theHeight * fHTE^^.lineHeight;
  390.         END;
  391.  
  392.     CalcRealHeight := theHeight;
  393.     {$IFC qDebug}
  394.     IF gIntenseDebugging THEN
  395.         WRITELN('CalcRealHeight=', theHeight: 0);
  396.     {$ENDC}
  397.     END;
  398.  
  399. {--------------------------------------------------------------------------------------------------}
  400. {$S TERes}
  401.  
  402. FUNCTION TTEView.CalcRealWidth: LONGINT;
  403.  
  404.     VAR
  405.         index: INTEGER;
  406.         wasLocked: BOOLEAN;
  407.         fromChar: INTEGER;
  408.         toChar: INTEGER;
  409.         aWidth: INTEGER;
  410.         theStyle: TextStyle;
  411.  
  412.     BEGIN
  413.     { !!! it would be nice to compute this for styled TE but TEGetPoint only returns the bottom
  414.     left of the character box so it can't be used to find the width including last character
  415.     in a line.    And since some characters can change width based on context we can't just
  416.     measure the last character and add it in.  Maybe we can makeup an formula based on
  417.     style runs or something eventually. }
  418.     CalcRealWidth := 0;    { Initialize the function result }
  419.     IF NOT fStyleType THEN
  420.         BEGIN
  421.         IF Focus THEN
  422.             BEGIN
  423.             theStyle := fTextStyle;
  424.             SetPortTextStyle(theStyle);
  425.         
  426.             aWidth := 0;
  427.             fromChar := fHTE^^.lineStarts[0];
  428.     
  429.             wasLocked := IsHandleLocked(fHTE^^.hText);
  430.             HLock(Handle(fHTE^^.hText));                        {??? Better to LockHandleHigh? }
  431.     
  432.             FOR index := 1 TO fHTE^^.nLines DO
  433.                 BEGIN
  434.                 toChar := fHTE^^.lineStarts[index] - 1;
  435.                 aWidth := Max(aWidth, TextWidth(fHTE^^.hText^, fromChar, (toChar - fromChar) + 1));
  436.                 fromChar := toChar + 1;
  437.                 END;
  438.     
  439.             IF NOT wasLocked THEN
  440.                 HUnlock(Handle(fHTE^^.hText));
  441.     
  442.             CalcRealWidth := aWidth;
  443.             END
  444.         END
  445.     ELSE IF qDebug THEN
  446.         ProgramBreak('IN TTEView.CalcRealWidth: called for a styled TE Record');
  447.     END;
  448.  
  449. {--------------------------------------------------------------------------------------------------}
  450. {$S TENonRes}
  451.  
  452. PROCEDURE TTEView.ChangeWrap(newAutoWrap, redraw: BOOLEAN);
  453.  
  454.     BEGIN
  455.     fAutoWrap := newAutoWrap;
  456.     WITH fHTE^^ DO
  457.         IF newAutoWrap THEN
  458.             crOnly := 0
  459.         ELSE
  460.             crOnly := - 1;
  461.     IF redraw THEN
  462.         BEGIN
  463.         RecalcText;
  464.         SynchView(kRedraw);
  465.         END;
  466.     END;
  467.  
  468. {--------------------------------------------------------------------------------------------------}
  469. {$S TENonRes}
  470.  
  471. PROCEDURE TTEView.ComputeSize(VAR newSize: VPoint); OVERRIDE;
  472.  
  473.     FUNCTION NeedAdjust(vhs: VHSelect): BOOLEAN;
  474.  
  475.         BEGIN
  476.         NeedAdjust := NOT (fSizeDeterminer[vhs] IN [sizeFixed, sizeSuperView, sizeRelSuperView]);
  477.         END;
  478.  
  479.     BEGIN                                                { TTEView.ComputeSize }
  480.     INHERITED ComputeSize(newSize);
  481.  
  482.     IF NeedAdjust(h) THEN                                { If necessary, tack on the margins }
  483.         newSize.h := Min(kMaxCoord, ORD4(newSize.h) + fInset.left + fInset.right);
  484.     IF NeedAdjust(v) THEN
  485.         newSize.v := Min(kMaxCoord, ORD4(newSize.v) + fInset.top + fInset.bottom);
  486.     END;
  487.  
  488. {--------------------------------------------------------------------------------------------------}
  489. {$S TERes}
  490.  
  491. PROCEDURE TTEView.CalcSelLoc(VAR selectionRect: Rect);
  492.  
  493.     CONST
  494.         kSlopToAllow        = 36;
  495.  
  496.     VAR
  497.         handleToText:        CharsHandle;
  498.         startOfSelection:    INTEGER;
  499.         endOfSelection:     INTEGER;
  500.         startOfCurrentLine: INTEGER;
  501.         startOfNextLine:    INTEGER;
  502.         charCount:            INTEGER;
  503.         selLine:            INTEGER;
  504.         upToSelWidth:        INTEGER;
  505.         restWidth:            INTEGER;
  506.         lineHeight:         INTEGER;
  507.         fontAscent:         INTEGER;
  508.         theStyle:            TextStyle;
  509.         keyDirection:        SignedByte;
  510.         selectionIsTheLastReturn: BOOLEAN;
  511.         theMode:            INTEGER;
  512.         theFontInfo:        FontInfo;
  513.         just:                INTEGER;
  514.  
  515.     BEGIN
  516.     WITH fHTE^^ DO
  517.         BEGIN
  518.         charCount := teLength;
  519.         startOfSelection := selStart;
  520.         endOfSelection := selEnd;
  521.         handleToText := CharsHandle(hText);
  522.  
  523.         IF (selEnd - selStart = 0) & (fIdleFreq = kMaxIdleTime) THEN
  524.             SetIdleFreq(0);                             { Idle ASAP }
  525.         END;
  526.  
  527.     {$Push} {$R-}
  528.     selectionIsTheLastReturn := (startOfSelection = charCount) & (charCount > 0) &
  529.                                 (handleToText^^[charCount - 1] = chReturn);
  530.     {$Pop}
  531.  
  532.     IF qNeedsStyleTextEdit | gConfiguration.hasStyleTextedit THEN
  533.         BEGIN
  534.         selectionRect.topLeft := TEGetPoint(startOfSelection, fHTE);
  535.  
  536.         { TEGetPoint returns the baseline point.  Correct for the lineheight }
  537.         TEGetStyle(startOfSelection, theStyle, lineHeight, fontAscent, fHTE);
  538.         selectionRect.top := selectionRect.top - lineHeight;
  539.  
  540.         selectionRect.botRight := TEGetPoint(endOfSelection, fHTE); { Darn! wish we could know where
  541.                                                                      the point to the bottom right
  542.                                                                      of an offset is!!! This way we
  543.                                                                      can't ever return the "real"
  544.                                                                      rectangle that encloses the
  545.                                                                      selection. }
  546.  
  547.         IF charCount = 0 THEN                            { In System 6 TE TEGetPoint returns bogus
  548.                                                          numbers when the character count is 0. }
  549.             WITH selectionRect DO
  550.                 BEGIN
  551.                 top := 0;
  552.                 bottom := lineHeight;
  553.                 END;
  554.  
  555.         IF selectionIsTheLastReturn THEN
  556.             BEGIN
  557.             theMode := doAll;
  558.  
  559.            { Get the style so we know how tall to make the selection when its just the last return }
  560.             IF ContinuousStyle(MAXINT, MAXINT, theMode, theStyle) THEN; { discard result }
  561.  
  562.             GetTextStyleFontInfo(theStyle, theFontInfo);
  563.  
  564.             selectionRect.top := selectionRect.bottom;
  565.             WITH theFontInfo DO
  566.                 selectionRect.bottom := selectionRect.top + ascent + descent + leading;
  567.             END
  568.         ELSE
  569.             BEGIN
  570. { Correct errors by CalcSelLoc.  If there is no selection then the "selection" consists of
  571. the bits enclosed by the insertion bar. }
  572.             WITH fHTE^^ DO
  573.                 BEGIN
  574.                 IF (selEnd - selStart = 0) THEN
  575.                     selectionRect.left := selectionRect.right - 1;
  576.                 END;
  577.  
  578.             END
  579.         END
  580.     ELSE                                                { Non-styled, ugh! do all the measuring
  581.                                                          ourselves }
  582.         BEGIN
  583.  
  584.         WITH fHTE^^ DO                                    { for lineStarts and nLines }
  585.             BEGIN
  586.             selLine := 1;
  587.             WHILE (selLine < nLines) & (startOfSelection >= lineStarts[selLine]) DO
  588.                 selLine := selLine + 1;
  589.             selLine := selLine - 1;
  590.  
  591.             IF selectionIsTheLastReturn | (fJustification <> teJustLeft) & (startOfSelection =
  592.                lineStarts[SUCC(selLine)]) THEN
  593.                 selLine := SUCC(selLine);
  594.  
  595.             selectionRect.top := (lineHeight * selLine) + fInset.top;
  596.             startOfCurrentLine := lineStarts[selLine];
  597.             IF selLine < nLines THEN
  598.                 startOfNextLine := lineStarts[SUCC(selLine)]
  599.             ELSE
  600.                 startOfNextLine := charCount;
  601.             END;
  602.  
  603.         { We could move the handle high first, but this routine is called frequently and
  604.         fragmentation shouldn't be a problem for the TextWidth call--the worst that will
  605.         happen is the Font Manager will have to substitute a font & we'll be off slightly.}
  606.         { ??? The following Text calls may be unnecessary, since this may only get done
  607.         after TextEdit has run and set the font already.  This appears not to be the case
  608.         for the Select All command, however, and is not true in general. }
  609.         TextFont(fHTE^^.txFont);
  610.         TextFace(fHTE^^.txFace);
  611.         TextSize(fHTE^^.txSize);
  612.         HLock(Handle(handleToText));
  613.  
  614.         { Figure out where on the line the selection is. If the Script Manager is
  615.         installed, use it. Otherwise, try and figure it out ourselves. }
  616.         IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  617.             BEGIN
  618.             { Unfortunately, we must get this every time, as the user can change script
  619.             directions at a moment's notice. }
  620.             IF startOfSelection = endOfSelection THEN
  621.                 keyDirection := GetScript(GetEnvirons(smKeyScript), smScriptRight)
  622.             ELSE
  623.                 keyDirection := smHilite;
  624.  
  625.             upToSelWidth := Char2Pixel(Ptr(ORD(handleToText^) + startOfCurrentLine),
  626.                                        startOfNextLine - startOfCurrentLine, 0, startOfSelection -
  627.                                        startOfCurrentLine, keyDirection);
  628.             restWidth := TextWidth(QDPtr(handleToText^), startOfCurrentLine, startOfNextLine -
  629.                                    startOfCurrentLine) - upToSelWidth;
  630.             END
  631.         ELSE
  632.             BEGIN
  633.             upToSelWidth := TextWidth(QDPtr(handleToText^), startOfCurrentLine, startOfSelection -
  634.                                       startOfCurrentLine);
  635.             restWidth := TextWidth(QDPtr(handleToText^), startOfSelection, startOfNextLine -
  636.                                    startOfSelection);
  637.             END;
  638.  
  639.         HUnlock(Handle(handleToText));
  640.  
  641.         just := fJustification;
  642.  
  643.         {!!!### come back and fix this or just stop supporting systems without style TE }
  644.         CASE just OF
  645.             teJustLeft:
  646.                 selectionRect.left := fInset.left + upToSelWidth;
  647.             teJustRight:
  648.                 selectionRect.left := fSize.h - fInset.right - restWidth;
  649.             { Following looks somewhat baroque, but avoids integer overflow }
  650.             teJustCenter:
  651.                 selectionRect.left := fSize.h DIV 2 - restWidth DIV 2 + upToSelWidth DIV 2;
  652.         END;
  653.  
  654.         WITH selectionRect DO
  655.             BEGIN
  656.             left := MAX(left - 2, 0);
  657.             IF left <= kSlopToAllow THEN
  658.                 left := 0;                                { show start of line if close; gets around }
  659.             { …potential annoyance assoc w/typeahead }
  660.             right := Min(left + 8, fSize.h);
  661.             bottom := Min(top + fHTE^^.lineHeight, fSize.v);
  662.             END;
  663.         END;
  664.     END;
  665.  
  666. {--------------------------------------------------------------------------------------------------}
  667. {$S TERes}
  668.  
  669. FUNCTION TTEView.ContinuousStyle(firstChar, lastChar: INTEGER;
  670.                                  VAR mode: INTEGER;
  671.                                  VAR aStyle: TextStyle): BOOLEAN;
  672.  
  673.     VAR
  674.         oldSelStart, oldSelEnd: INTEGER;
  675.  
  676.     BEGIN
  677.     WITH fHTE^^ DO
  678.         BEGIN
  679.         oldSelStart := selStart;
  680.         oldSelEnd := selEnd;
  681.         END;
  682.     SetSelect(firstChar, lastChar, fHTE);                { Use SetSelect so this is invisible }
  683.     ContinuousStyle := TEContinuousStyle(mode, aStyle, fHTE);
  684.     SetSelect(oldSelStart, oldSelEnd, fHTE);
  685.     END;
  686.  
  687. {--------------------------------------------------------------------------------------------------}
  688. {$S TERes}
  689.  
  690. FUNCTION TTEView.ContainsClipType(aType: ResType): BOOLEAN; OVERRIDE;
  691.  
  692.     BEGIN
  693.     ContainsClipType := (aType = 'TEXT');
  694.     END;
  695.  
  696. {--------------------------------------------------------------------------------------------------}
  697. { Put in resident segment since this gets called while typing }
  698. {$S TERes}
  699.  
  700. FUNCTION TTEView.DoBreakFollowing(vhs: VHSelect;
  701.                                   prevBreak: VCoordinate;
  702.                                   VAR automatic: BOOLEAN): VCoordinate; OVERRIDE;
  703.  
  704.     VAR
  705.         orthoVhs:            VHSelect;
  706.         possibleLoc:        INTEGER;
  707.         theStyles:            TEStyleHandle;
  708.         lhTab:                LHHandle;
  709.         height, lineHeight: INTEGER;
  710.         lineNo:             INTEGER;
  711.  
  712.     BEGIN
  713.     orthoVhs := gOrthogonal[vhs];
  714.     automatic := TRUE;
  715.  
  716.     possibleLoc := Min(kMaxCoord, ORD4(prevBreak) + fPrintHandler.fViewPerPage.vh[orthoVhs]);
  717.  
  718.  { We want to get rid of the on-screen margin represented by fMargin when printing, so
  719.    adjust things so that the portion of the view occupied by the screen margin doesn't
  720.    get printed. }
  721.     IF prevBreak = 0 THEN
  722.         possibleLoc := possibleLoc + fInset.topLeft.vh[orthoVhs];
  723.  
  724.     IF (fStyleType = kWithStyle) & (vhs = h) THEN
  725.         BEGIN
  726.         IF (fLastPageBreak = prevBreak) THEN
  727.             BEGIN
  728.             height := fLastPageBreak;
  729.             lineNo := fLastLine;
  730.             END
  731.         ELSE
  732.             BEGIN
  733.             height := fInset.topLeft.vh[orthoVhs];
  734.             lineNo := 0;
  735.             END;
  736.  
  737.         theStyles := GetStylHandle(fHTE);
  738.         lhTab := theStyles^^.lhTab;
  739.         WHILE lineNo < fHTE^^.nLines DO
  740.             BEGIN
  741.             lineHeight := lhTab^^[lineNo].lhHeight;
  742.             IF height + lineHeight <= possibleLoc THEN
  743.                 height := height + lineHeight
  744.             ELSE
  745.                 LEAVE;
  746.             lineNo := lineNo + 1;
  747.             END;
  748.         IF lineNo >= fHTE^^.nLines THEN
  749.             possibleLoc := MAX(possibleLoc, height)
  750.         ELSE
  751.             possibleLoc := height;
  752.         fLastPageBreak := possibleLoc;
  753.         fLastLine := lineNo;
  754.         END;
  755.  
  756.     IF ORD4(possibleLoc + fInset.topLeft.vh[orthoVhs]) >= fSize.vh[orthoVhs] THEN
  757.         DoBreakFollowing := fSize.vh[orthoVhs]
  758.     ELSE
  759.         DoBreakFollowing := possibleLoc;
  760.     END;
  761.  
  762. {--------------------------------------------------------------------------------------------------}
  763. {$S TENonRes}
  764.  
  765. PROCEDURE TTEView.DoCalcViewPerPage(VAR viewPerPage: VPoint); OVERRIDE;
  766.  
  767.     VAR
  768.         vhs:                VHSelect;
  769.  
  770.     BEGIN
  771.     INHERITED DoCalcViewPerPage(viewPerPage);            { Get max amount allowed given margins }
  772.  
  773.     {$IFC qDebug}
  774.     IF gDebugPrinting THEN
  775.         BEGIN
  776.         WRITE('TTEView: incoming generic viewPerPage:');
  777.         WriteVPt(viewPerPage);
  778.         WRITELN;
  779.         END;
  780.     {$ENDC}
  781.  
  782.     IF (fStyleType <> kWithStyle) & (fHTE <> NIL) THEN    { Adjust for integral # of lines per page }
  783.         WITH fHTE^^ DO
  784.             viewPerPage.v := lineHeight * (viewPerPage.v DIV lineHeight);
  785.  
  786.     {$IFC qDebug}
  787.     IF gDebugPrinting THEN
  788.         BEGIN
  789.         WRITE('TTEView: computed viewPerPage:');
  790.         WriteVPt(viewPerPage);
  791.         WRITELN;
  792.         END;
  793.     {$ENDC}
  794.     END;
  795.  
  796. {--------------------------------------------------------------------------------------------------}
  797. {$S TERes}
  798.  
  799. FUNCTION TTEView.DoIdle(phase: IdlePhase): BOOLEAN; OVERRIDE;
  800.  
  801.     VAR
  802.         aRect:                Rect;
  803.  
  804.     BEGIN
  805.     DoIdle := FALSE;                                    { Didn't free myself }
  806.  
  807.     IF (fHTE <> NIL) & (fHTE^^.selEnd - fHTE^^.selStart = 0) & fViewEnabled THEN
  808.         BEGIN
  809.         IF Focus & IsVisible & fAcceptsChanges THEN
  810.             TEIdle(fHTE);
  811.         SetIdleFreq(MAX(GetCaretTime DIV 2, 1));        { Reset idle frequency in case user changed
  812.                                                          it}
  813.         END
  814.     ELSE
  815.         SetIdleFreq(kMaxIdleTime);                        { No need to bother anyone. }
  816.     END;
  817.  
  818. {--------------------------------------------------------------------------------------------------}
  819. {$S TERes}
  820.  
  821. FUNCTION TTEView.DoKeyCommand(ch: Char;
  822.                               aKeyCode: INTEGER;
  823.                               VAR info: EventInfo): TCommand; OVERRIDE;
  824. { The Tab character has no width in some fonts, and so can cause confusing screen feedback.
  825.  It is filtered out by default.  If you want to include it in your text union it into fControlChars. }
  826.  
  827.     VAR
  828.         aTypingCommand:     TTETypingCommand;
  829.         needNewCommand:     BOOLEAN;
  830.         handledCharacter:    BOOLEAN;
  831.  
  832.     BEGIN
  833.     DoKeyCommand := NIL;
  834.     handledCharacter := FALSE;
  835.  
  836.     IF IsViewEnabled THEN                                { if view is not enabled then we don't take
  837.                                                          ANY keystrokes }
  838.         BEGIN
  839.         IF (ch >= ' ') | (ch IN fControlChars) THEN     { Check that the character should be
  840.                                                          accepted }
  841.             BEGIN
  842.             IF (ch IN [chLeft, chRight, chUp, chDown]) & Focus THEN { check for pure movement keys }
  843.                 BEGIN
  844.                 DoneTyping;                             { Like mousedown, further typing = new cmd }
  845.                 fSpecsChanged := TRUE;
  846.                 TEKey(ch, fHTE);
  847.                 ScrollSelectionIntoView;
  848.                 handledCharacter := TRUE;
  849.                 END
  850.             ELSE IF fAcceptsChanges & Focus THEN
  851.                 BEGIN
  852.                 { Check max size for text, and that we're not running out of memory }
  853.                 IF (ch <> chBackspace) & (ch <> chFwdDelete) & (fHTE^^.selStart =
  854.                    fHTE^^.selEnd) THEN
  855.                     IF ((fMaxChars - GetHandleSize(fText)) < 1) | MemSpaceIsLow THEN
  856.                         BEGIN
  857.                         StdAlert(phTooManyChars);
  858.                         EXIT(DoKeyCommand);             { Flush further keystrokes }
  859.                         END;
  860.  
  861.                 { Pass the character to the typing command, creating a new one if necessary }
  862.  
  863.                 needNewCommand := (fTypingCommand = NIL);
  864.                 IF NOT needNewCommand THEN
  865.                     needNewCommand := fTypingCommand.fCompleted;
  866.  
  867.                 IF needNewCommand THEN
  868.                     BEGIN
  869.                     aTypingCommand := DoMakeTypingCommand(ch);
  870.                     fTypingCommand := aTypingCommand;
  871.                     DoKeyCommand := aTypingCommand;
  872.                     END
  873.                 ELSE
  874.                     BEGIN
  875.                     fTypingCommand.AddCharacter(ch);
  876.                     { Once you're typing (first character already processed) collecting subsequent
  877.                     characters really shouldn't affect the menus unless you're keeping a character
  878.                     count in them or something that depends on the aggregate of the characters you've
  879.                     typed.    The TextStyle for the first character would certainly apply to subsequent
  880.                     characters.  So, this is one ideal place to say that the event _DOES NOT_ affect
  881.                     the menus.    If the menus are already invalid they will stay so, but if they are
  882.                     valid then there is no need to invalidate them in the character collection process.
  883.                     When the user terminates the addition of characters with another event, the menus
  884.                     will be setup from that event.    If you really feel you must, then you can always
  885.                     override, call inherited and then set info.affectMenus back to true. (Rhymes with
  886.                     rue) }
  887.                     info.affectsMenus := FALSE;
  888.                     END;
  889.                 handledCharacter := TRUE;
  890.                 END
  891.  
  892.             END;
  893.         IF fIdleFreq = kMaxIdleTime THEN
  894.             SetIdleFreq(0);                             { Idle ASAP, since someone may somehow set
  895.                                                          an insertion point and want it to flash.
  896.                                                          (the idle time will be reset to match the
  897.                                                          caret time in doidle.)}
  898.         END;
  899.  
  900.     IF NOT handledCharacter THEN
  901.         DoKeyCommand := INHERITED DoKeyCommand(ch, aKeyCode, info);
  902.     END;
  903.  
  904. {--------------------------------------------------------------------------------------------------}
  905. {$S TESelCommand}
  906.  
  907. FUNCTION TTEView.DoMakeEditCommand(aCmdNumber: CmdNumber): TTECommand;
  908.  
  909.     VAR
  910.         aCutCopyCommand:    TTECutCopyCommand;
  911.         aPasteCommand:        TTEPasteCommand;
  912.         aClearCommand:        TTECommand;
  913.  
  914.     BEGIN
  915.     CASE aCmdNumber OF
  916.         cCut, cCopy:
  917.             BEGIN
  918.             New(aCutCopyCommand);
  919.             FailNIL(aCutCopyCommand);
  920.             aCutCopyCommand.ITECutCopyCommand(SELF, aCmdNumber);
  921.             DoMakeEditCommand := aCutCopyCommand;
  922.             END;
  923.  
  924.         cPaste:
  925.             BEGIN
  926.             New(aPasteCommand);
  927.             FailNIL(aPasteCommand);
  928.             aPasteCommand.ITEPasteCommand(SELF);
  929.             DoMakeEditCommand := aPasteCommand;
  930.             END;
  931.  
  932.         cClear:
  933.             BEGIN
  934.             New(aClearCommand);
  935.             FailNIL(aClearCommand);
  936.             aClearCommand.ITECommand(SELF, aCmdNumber, TRUE);
  937.             DoMakeEditCommand := aClearCommand;
  938.             END;
  939.  
  940.     END;
  941.     END;
  942.  
  943. {--------------------------------------------------------------------------------------------------}
  944. {$S TERes}
  945.  
  946. FUNCTION TTEView.DoMakeStyleCommand(aStyle: TextStyle;
  947.                                     itsCmdNumber: CmdNumber;
  948.                                     itsMode: INTEGER): TTEStyleCommand;
  949.  
  950.     VAR
  951.         aTEStyleCommand:    TTEStyleCommand;
  952.  
  953.     BEGIN
  954.     New(aTEStyleCommand);
  955.     FailNIL(aTEStyleCommand);
  956.     aTEStyleCommand.ITEStyleCommand(SELF, aStyle, itsCmdNumber, itsMode);
  957.     DoMakeStyleCommand := aTEStyleCommand;
  958.     END;
  959.  
  960. {--------------------------------------------------------------------------------------------------}
  961. {$S TERes}
  962.  
  963. FUNCTION TTEView.DoMakeTypingCommand(ch: Char): TTETypingCommand;
  964.  
  965.     VAR
  966.         aTypingCommand:     TTETypingCommand;
  967.  
  968.     BEGIN
  969.     New(aTypingCommand);
  970.     FailNIL(aTypingCommand);
  971.     aTypingCommand.ITETypingCommand(SELF, ch);
  972.     DoMakeTypingCommand := aTypingCommand;
  973.     END;
  974.  
  975. {--------------------------------------------------------------------------------------------------}
  976. {$S TESelCommand}
  977.  
  978. FUNCTION TTEView.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; OVERRIDE;
  979.  
  980.     VAR
  981.         command:            TCommand;
  982.         aCutCopyCommand:    TTECutCopyCommand;
  983.         aPasteCommand:        TTEPasteCommand;
  984.         nChars:             LONGINT;
  985.         dataType:            ResType;
  986.  
  987.     BEGIN
  988.     DoMenuCommand := NIL;
  989.     CASE aCmdNumber OF
  990.         cCut, cCopy, cClear:
  991.             DoMenuCommand := DoMakeEditCommand(aCmdNumber);
  992.  
  993.         cPaste:
  994.             BEGIN
  995.             nChars := gApplication.GetDataToPaste(NIL, dataType);
  996.             IF nChars < 0 THEN
  997.             {$IFC qDebug}
  998.                 ProgramBreak('Couldn''t get data to paste') { ??? }
  999.                 {$ENDC}
  1000.             ELSE
  1001.                 BEGIN
  1002.                 IF nChars - (fHTE^^.selEnd - fHTE^^.selStart) >
  1003.                    fMaxChars - GetHandleSize(fText) THEN
  1004.                     StdAlert(phTooManyChars)
  1005.                 ELSE
  1006.                     DoMenuCommand := DoMakeEditCommand(aCmdNumber);
  1007.                 END;
  1008.             END;
  1009.  
  1010.         cSelectAll:
  1011.             BEGIN
  1012.             IF Focus THEN
  1013.                 BEGIN
  1014.                 TESetSelect(0, fHTE^^.teLength, fHTE);
  1015.                 DoneTyping;
  1016.                 fSpecsChanged := TRUE;
  1017.                 ScrollSelectionIntoView;
  1018.                 END;
  1019.             END;
  1020.  
  1021.         OTHERWISE
  1022.             DoMenuCommand := INHERITED DoMenuCommand(aCmdNumber);
  1023.  
  1024.     END;
  1025.     END;
  1026.  
  1027. {--------------------------------------------------------------------------------------------------}
  1028. {$S TERes}
  1029.  
  1030. FUNCTION TTEView.DoMouseCommand(VAR theMouse: Point;
  1031.                                 VAR info: EventInfo;
  1032.                                 VAR hysteresis: Point): TCommand; OVERRIDE;
  1033.  
  1034.     BEGIN
  1035.     IF Focus & IsVisible THEN
  1036.         BEGIN
  1037.         pCurrTEView := SELF;                            { So the global clikLoop routine can forward
  1038.                                                          }
  1039.         DoneTyping;                                     { Mousedown terminates the Typing command }
  1040.         fSpecsChanged := TRUE;
  1041.         TEClick(theMouse, info.theShiftKey, fHTE);
  1042.  
  1043.         { …force a re-focus b/c the focusing in ClikLoop clips down to the destrect. }
  1044.         IF IsFocused THEN
  1045.             InvalidateFocus;
  1046.  
  1047.         IF fIdleFreq = kMaxIdleTime THEN
  1048.             SetIdleFreq(0);                             { Idle ASAP }
  1049.         END;
  1050.     DoMouseCommand := NIL;
  1051.     END;
  1052.  
  1053. {--------------------------------------------------------------------------------------------------}
  1054. {$S TENonRes}
  1055.  
  1056. PROCEDURE TTEView.DoneTyping;
  1057.  
  1058.     BEGIN
  1059.     IF fTypingCommand <> NIL THEN
  1060.         fTypingCommand.CompleteTyping;
  1061.     END;
  1062.  
  1063. {--------------------------------------------------------------------------------------------------}
  1064. {$S TERes}
  1065.  
  1066. FUNCTION TTEView.DoSetCursor(localPoint: Point;
  1067.                              cursorRgn: RgnHandle): BOOLEAN; OVERRIDE;
  1068.  
  1069.     VAR
  1070.         qdExtent:            Rect;
  1071.  
  1072.     BEGIN
  1073.     GetDefaultCursorRgn(localPoint,cursorRgn);
  1074.     UseROMMap(TRUE);
  1075.     SetCursor(GetCursor(iBeamCursor)^^);
  1076.     DoSetCursor := TRUE;
  1077.     END;
  1078.  
  1079. {--------------------------------------------------------------------------------------------------}
  1080. {$S TEPrint}
  1081.  
  1082. PROCEDURE TTEView.DoSetPageOffset(coord: VPoint); OVERRIDE;
  1083.  
  1084.     VAR
  1085.         vhs:                VHSelect;
  1086.  
  1087.     BEGIN
  1088.     INHERITED DoSetPageOffset(coord);
  1089.     FOR vhs := v TO h DO
  1090.         IF coord.vh[vhs] = 0 THEN
  1091.             gPageOffset.vh[vhs] := gPageOffset.vh[vhs] + fInset.topLeft.vh[vhs];
  1092.     END;
  1093.  
  1094. {--------------------------------------------------------------------------------------------------}
  1095. {$S TERes}
  1096.  
  1097. PROCEDURE TTEView.DoSetupMenus; OVERRIDE;
  1098.  
  1099.     VAR
  1100.         manyChars:            BOOLEAN;
  1101.  
  1102.     BEGIN
  1103.     INHERITED DoSetupMenus;
  1104.  
  1105.     WITH fHTE^^ DO
  1106.         manyChars := selStart < selEnd;
  1107.     IF NOT MemSpaceIsLow THEN
  1108.         BEGIN
  1109.         IF fAcceptsChanges THEN                         { One way or another, we can paste text }
  1110.             CanPaste('TEXT');                            { If styles exist, all the better }
  1111.  
  1112.         Enable(cCopy, manyChars);
  1113.         END;
  1114.     Enable(cSelectAll, (fHTE^^.teLength > 0));
  1115.  
  1116.  { We enable Cut even if space is low, since it's nice to be able to rescue some of
  1117.    the stuff you have to delete even if space is low.  Note that it is possible to
  1118.    get into the "can't do any commands" situation as a result.  You should be able
  1119.    to close and save the big document, then save the rescued text elsewhere, however. }
  1120.  
  1121.     Enable(cCut, manyChars & fAcceptsChanges);
  1122.     Enable(cClear, manyChars & fAcceptsChanges);
  1123.     END;
  1124.  
  1125. {--------------------------------------------------------------------------------------------------}
  1126. {$S TERes}
  1127.  
  1128. PROCEDURE TTEView.Draw(area: Rect); OVERRIDE;
  1129.  
  1130.     VAR
  1131.         hideSelection: BOOLEAN;
  1132.         
  1133.  
  1134.     BEGIN
  1135.     hideSelection := (gPrinting | gDrawingPictScrap) & BOOLEAN(fHTE^^.active);
  1136.     IF hideSelection THEN
  1137.         BEGIN                                        { …prevent selection from being drawn. }
  1138.         {$IFC qDebug}
  1139.         UseTempRgn('TTEView.Draw');
  1140.         {$ENDC}
  1141.         GetClip(gTempRgn);
  1142.         ClipRect(gZeroRect);
  1143.         TEDeactivate(fHTE);
  1144.         SetClip(gTempRgn);
  1145.         END;
  1146.  
  1147.  
  1148.     TEUpdate(area, fHTE);                { normal screen update handled by TextEdit directly }
  1149.  
  1150.     IF hideSelection THEN
  1151.         BEGIN
  1152.         GetClip(gTempRgn);
  1153.         ClipRect(gZeroRect);
  1154.         TEActivate(fHTE);
  1155.         SetClip(gTempRgn);
  1156.         {$IFC qDebug}
  1157.         DoneWithTempRgn;
  1158.         {$ENDC}
  1159.         END;
  1160.  
  1161.  
  1162.     INHERITED Draw(area);
  1163.     END;
  1164.  
  1165. {--------------------------------------------------------------------------------------------------}
  1166. {$S TENonRes}
  1167.  
  1168. PROCEDURE TTEView.ExtractStyles(VAR theStyles: TEStyleHandle;
  1169.                                 VAR theElements: STHandle);
  1170.  
  1171.     BEGIN
  1172.     theStyles := GetStylHandle(fHTE);
  1173.     theElements := theStyles^^.styleTab;
  1174.     END;
  1175.  
  1176. {--------------------------------------------------------------------------------------------------}
  1177. {$S TENonRes}
  1178.  
  1179. FUNCTION TTEView.ExtractText: Handle;
  1180.  
  1181.     BEGIN
  1182.     ExtractText := fText;
  1183.     END;
  1184.  
  1185. {--------------------------------------------------------------------------------------------------}
  1186. {$S TENonRes}
  1187.  
  1188. PROCEDURE TTEView.GetPrintExtent(VAR printExtent: VRect); OVERRIDE;
  1189.  
  1190.     BEGIN
  1191.     INHERITED GetPrintExtent(printExtent);
  1192.     WITH fInset DO
  1193.         BEGIN
  1194.         printExtent.top := printExtent.top + top;
  1195.         printExtent.left := printExtent.left + left;
  1196.         printExtent.bottom := printExtent.bottom - bottom;
  1197.         printExtent.right := printExtent.right - right;
  1198.         END;
  1199.     END;
  1200.  
  1201. {--------------------------------------------------------------------------------------------------}
  1202. {$S TEClipboard}
  1203.  
  1204. FUNCTION TTEView.GivePasteData(aDataHandle: Handle;
  1205.                                dataType: ResType): LONGINT; OVERRIDE;
  1206.  
  1207.     VAR
  1208.         oldStart:            INTEGER;
  1209.         oldEnd:             INTEGER;
  1210.         aSize:                LONGINT;
  1211.         aHandle:            Handle;
  1212.         err:                OSErr;
  1213.         savedPerm:            BOOLEAN;
  1214.         fi:                 FailInfo;
  1215.  
  1216. {--------------------------------------------------------------------------------------------------}
  1217.  
  1218.     PROCEDURE HdlGivePasteFailed(error: OSErr;
  1219.                                  message: LONGINT);
  1220.  
  1221.         BEGIN
  1222.         aHandle := DisposeIfHandle(aHandle);
  1223.         END;
  1224.  
  1225.     BEGIN
  1226.     savedPerm := FALSE;
  1227.     aSize := 0;                                         { Assume the worst }
  1228.     aHandle := NIL;
  1229.     CatchFailures(fi, HdlGivePasteFailed);
  1230.  
  1231.     IF dataType = 'TEXT' THEN
  1232.         BEGIN
  1233.         aSize := GetHandleSize(fText);
  1234.         IF aDataHandle <> NIL THEN
  1235.             BEGIN
  1236.             SetPermHandleSize(aDataHandle, aSize);        { Don't forget. This can fail }
  1237.             BlockMove(fText^, aDataHandle^, aSize);
  1238.             END;
  1239.         END
  1240.     ELSE IF dataType = 'styl' THEN
  1241.         BEGIN
  1242.         IF fStyleType = kWithStyle THEN
  1243.             IF NOT SpaceForStyles(0, MAXINT) THEN
  1244.                 Failure(noErr, 0)                        { We'll accept this error in worst case }
  1245.             ELSE
  1246.                 BEGIN
  1247.                 WITH fHTE^^ DO
  1248.                     BEGIN
  1249.                     oldStart := selStart;
  1250.                     oldEnd := selEnd;
  1251.                     END;
  1252.                 SetSelect(0, MAXINT, fHTE);
  1253.                 aHandle := Handle(GetStylScrap(fHTE));
  1254.                 SetSelect(oldStart, oldEnd, fHTE);
  1255.  
  1256.                 IF aHandle <> NIL THEN
  1257.                     BEGIN
  1258.                     aSize := GetHandleSize(aHandle);
  1259.                     IF aDataHandle <> NIL THEN
  1260.                         BEGIN
  1261.                         savedPerm := PermAllocation(TRUE);
  1262.                         LockHandleHigh(aHandle);        { Try to prevent fragmentation, in case
  1263.                                                          Can't move while we're copying it! }
  1264.  
  1265.                         err := PtrToXHand(aHandle^,     { Copy styles into user-supplied handle }
  1266.                                           aDataHandle, aSize);
  1267.                         HUnlock(aHandle);                { Okay for it to move again }
  1268.                         savedPerm := PermAllocation(savedPerm);
  1269.                         IF err <> noErr THEN            { Maybe enough for one copy, but not two! }
  1270.                             Failure(phStylesTooBig, phStylesTooBig + msgAlert);
  1271.                         END;
  1272.                     aHandle := DisposeIfHandle(aHandle);
  1273.                     END
  1274.                 ELSE IF aDataHandle <> NIL THEN         { Hmm. There _was_ enough memory, but the }
  1275.                     Failure(phStylesTooBig, phStylesTooBig + msgAlert); { …heap is probably pretty
  1276.                                                                          fragmented }
  1277.  
  1278.                 END;
  1279.         END
  1280.     ELSE
  1281.         Failure(noTypeErr, 0);
  1282.  
  1283.     FailSpaceIsLow;
  1284.     Success(fi);
  1285.     GivePasteData := aSize;
  1286.     END;
  1287.  
  1288. {--------------------------------------------------------------------------------------------------}
  1289. {$S TENonRes}
  1290.  
  1291. PROCEDURE TTEView.InstallSelection(wasActive, beActive: BOOLEAN); OVERRIDE;
  1292.  
  1293.     VAR
  1294.         aDiscard:            INTEGER;
  1295.  
  1296.     BEGIN
  1297.     IF fHTE <> NIL THEN                                 { fHTE is set to NIL by TTEView.Free …since
  1298.                                                          InstallSelection is then …called by
  1299.                                                          INHERITED Free. }
  1300.         BEGIN
  1301.         IF beActive THEN
  1302.             BEGIN
  1303.             IF fIdleFreq = kMaxIdleTime THEN
  1304.                 SetIdleFreq(0);                         { Idle ASAP }
  1305.             IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  1306.                 aDiscard := SetKeyScript(Font2Script(fTextStyle.tsFont));
  1307.             IF Focus THEN                                { Try to focus because TEActivate may draw }
  1308.                 TEActivate(fHTE);
  1309.             pCurrTEView := SELF;                        { So the global clikLoop routine can forward
  1310.                                                          }
  1311.             END
  1312.         ELSE
  1313.             BEGIN
  1314.             IF Focus THEN                                { Try to focus because TEDeactivate may draw
  1315.                                                          }
  1316.                 TEDeactivate(fHTE);
  1317.             DoneTyping;
  1318.             fSpecsChanged := TRUE;
  1319.             END;
  1320.         END;
  1321.     END;
  1322.  
  1323. {--------------------------------------------------------------------------------------------------}
  1324. {$S TEOpen}
  1325.  
  1326. PROCEDURE TTEView.MakeTERecord;
  1327.  
  1328.     VAR
  1329.         anHTE:                TEHandle;
  1330.         dest:                Rect;
  1331.         oldPort:            GrafPtr;
  1332.         fi:                 FailInfo;
  1333.         aTextStyle:         TextStyle;
  1334.  
  1335.     PROCEDURE HdlMakeFailed(error: OSErr;
  1336.                             message: LONGINT);
  1337.  
  1338.         BEGIN
  1339.         Free;
  1340.         END;
  1341.  
  1342.     BEGIN
  1343.     GetPort(oldPort);
  1344.     SetPort(gWorkPort);
  1345.     aTextStyle := fTextStyle;
  1346.     SetPortTextStyle(aTextStyle);
  1347.  
  1348.     dest.topLeft := fInset.topLeft;
  1349.     dest.right := fSize.h - fInset.right;
  1350.     dest.bottom := fSize.v - fInset.bottom;
  1351.  
  1352.     IF fStyleType = kWithStyle THEN
  1353.         anHTE := TEStylNew(dest, dest)                    { Open a styled record if requested }
  1354.     ELSE
  1355.         anHTE := TENew(dest, dest);                     { …otherwise, do it the old way }
  1356.  
  1357.     SetPort(oldPort);
  1358.  
  1359.     CatchFailures(fi, HdlMakeFailed);                    { In case we couldn't create the TEHandle. }
  1360.     FailNIL(anHTE);                                     { Make sure we actually created one }
  1361.     fHTE := anHTE;                                        { We did, so save off TE handle }
  1362.     gDefClikLoopProc := anHTE^^.ClikLoop;                { Just in case we want to restore it… }
  1363.     { Note that the system call SetClikLoop }
  1364.     { _cannot_ be used to set the clikProc of }
  1365.     { the TERecord. This is because the default }
  1366.     { clikproc does not follow the Pascal Parameter }
  1367.     { passing conventions that this procedure expects. }
  1368.  
  1369.     SetJustification(fJustification, kDontRedraw);        { Set justification to requested value }
  1370.     ChangeWrap(fAutoWrap, FALSE);                        { Install auto wrap (or CR only) }
  1371.     FailNoReserve;                                        { Got to have some reserve tank }
  1372.     Success(fi);
  1373.  
  1374.     BeInPort(GetGrafPort);                                { Associate with real port }
  1375.     END;
  1376.  
  1377. {--------------------------------------------------------------------------------------------------}
  1378. {$S TERes}
  1379.  
  1380. PROCEDURE TTEView.RecalcText;
  1381.  
  1382.     BEGIN
  1383.     TECalText(fHTE);
  1384.     END;
  1385.  
  1386. {--------------------------------------------------------------------------------------------------}
  1387. {$S TENonRes}
  1388.  
  1389. PROCEDURE TTEView.Resize(width, height: VCoordinate;
  1390.                          invalidate: BOOLEAN); OVERRIDE;
  1391.  
  1392.     VAR
  1393.         needCalText:        BOOLEAN;
  1394.         r:                    Rect;
  1395.         oldSize:            VPoint;
  1396.         actualJust:            INTEGER;
  1397.  
  1398.     BEGIN
  1399.     oldSize := fSize;
  1400.     INHERITED Resize(width, height, invalidate);
  1401.     IF fHTE <> NIL THEN
  1402.         BEGIN
  1403.         r.topLeft := fInset.topLeft;
  1404.         r.right := fSize.h - fInset.right;
  1405.         r.bottom := fSize.v - fInset.bottom;
  1406.  
  1407.         needCalText := (r.right <> fHTE^^.destRect.right);
  1408.         StuffTERects(r);
  1409.         IF needCalText THEN
  1410.             BEGIN
  1411.             RecalcText;
  1412.             SynchView(kDontRedraw);
  1413.             actualJust := GetActualJustification(fJustification);
  1414.             IF invalidate & ((fAutoWrap & ((fSize.h <> oldSize.h) | (fSize.v <> oldSize.v)))
  1415.             { All bets are off }
  1416.             | ((actualJust = teJustRight) | (actualJust = teJustCenter))) THEN
  1417.                 ForceRedraw;
  1418.             END;
  1419.         END;
  1420.     END;
  1421.  
  1422. {--------------------------------------------------------------------------------------------------}
  1423. {$S TERes}
  1424.  
  1425. PROCEDURE TTEView.ScrollSelectionIntoView;
  1426.  
  1427.     VAR
  1428.         vhs:                VHSelect;
  1429.         newLoc:             Point;
  1430.         newSelLoc:            Point;
  1431.         selectionRect:        Rect;
  1432.         minToSee:            Point;
  1433.         visRect:            Rect;
  1434.         vSelectionRect:     VRect;
  1435.  
  1436.     BEGIN
  1437.     { ??? should we have an option to walk the superviews, scrolling as many scrollers as necessary
  1438.     to reveal the selection? }
  1439.     IF (GetScroller(FALSE) <> NIL) & Focus THEN         { Can't scroll selection if we don't have }
  1440.         BEGIN                                            { … a scroller! }
  1441.         IF fIdleFreq = kMaxIdleTime THEN
  1442.             SetIdleFreq(0);                             { Idle ASAP }
  1443.         GetVisibleRect(visRect);
  1444.         CalcSelLoc(selectionRect);
  1445.  
  1446.         {$IFC qDebug}
  1447.         IF gIntenseDebugging THEN
  1448.             BEGIN
  1449.             WRITE('Visible Rect was: '); WriteRect(visRect);
  1450.             WRITE('; Sel Rect was: '); WriteRect(selectionRect); WRITELN;
  1451.             END;
  1452.         {$ENDC}
  1453.  
  1454.         IF NOT RectsNest(visRect, selectionRect) THEN
  1455.             BEGIN
  1456.             { Scroll the selection into view.  accounting for the user's preference for how much to
  1457.             jump at a time with fMinAhead. }
  1458.             SetPt(minToSee, Min(fMinAhead, fSize.h - selectionRect.left), LengthRect(selectionRect,
  1459.                   v));
  1460.             {$IFC qDebug}
  1461.             IF gIntenseDebugging THEN
  1462.                 BEGIN
  1463.                 WrLblRect('RevealRect: r', selectionRect);
  1464.                 WrLblPt(', minToSee', minToSee);
  1465.                 WRITELN;
  1466.                 END;
  1467.             {$ENDC}
  1468.             QDToViewRect(selectionRect, vSelectionRect);
  1469.             RevealRect(vSelectionRect, minToSee, kRedraw);
  1470.             IF Focus THEN;                                { Refocus in newly-scrolled position. Why???
  1471.                                                          does our caller have a dependency on this?
  1472.                                                          }
  1473.             END;
  1474.         END
  1475.     ELSE IF qNeedsROM128K | gConfiguration.hasROM128K THEN
  1476.         IF NOT fAutoWrap & (fHTE <> NIL) THEN
  1477.             TESelView(fHTE);
  1478.     END;
  1479.  
  1480. {--------------------------------------------------------------------------------------------------}
  1481. {$S TENonRes}
  1482.  
  1483. PROCEDURE TTEView.SetJustification(newJust: INTEGER;
  1484.                                    redraw: BOOLEAN);
  1485.  
  1486.     BEGIN
  1487.     TESetJust(newJust, fHTE);
  1488.     fJustification := newJust;
  1489.     IF redraw THEN
  1490.         ForceRedraw;
  1491.     END;
  1492.  
  1493. {--------------------------------------------------------------------------------------------------}
  1494. {$S TENonRes}
  1495.  
  1496. PROCEDURE TTEView.SetOneStyle(theStart, theEnd, theMode: INTEGER;
  1497.                               theStyle: TextStyle;
  1498.                               redraw: BOOLEAN);
  1499.  
  1500.     VAR
  1501.         saveStart:            INTEGER;
  1502.         saveEnd:            INTEGER;
  1503.         fInfo:                FontInfo;
  1504.         newStyle:            TextStyle;
  1505.  
  1506.     BEGIN
  1507.     InvalidateFocus;                                    { ??? THIS SHOULDN'T BE NECESSARY! ??? }
  1508.     IF Focus THEN;
  1509.     IF fStyleType = kWithStyle THEN
  1510.         BEGIN
  1511.         WITH fHTE^^ DO
  1512.             BEGIN
  1513.             saveStart := selStart;
  1514.             saveEnd := selEnd;
  1515.             END;
  1516.         SetSelect(theStart, theEnd, fHTE);
  1517.         TESetStyle(theMode, theStyle, redraw, fHTE);
  1518.         SetSelect(saveStart, saveEnd, fHTE);
  1519.         END
  1520.     ELSE
  1521.         BEGIN
  1522.         IF theMode = doAll THEN
  1523.             newStyle := theStyle
  1524.         ELSE
  1525.             BEGIN
  1526.             newStyle := fTextStyle;
  1527.             IF BAND(theMode, doFont) <> 0 THEN
  1528.                 BEGIN
  1529.                 newStyle.tsFont := theStyle.tsFont;
  1530.  
  1531.                 IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN { …if Script Mgr is
  1532.                        installed, change }
  1533.                     KeyScript(Font2Script(newStyle.tsFont)); { …keybd input system to match new font
  1534.                                                               }
  1535.                 END;
  1536.             IF BAND(theMode, doFace) <> 0 THEN
  1537.                 newStyle.tsFace := theStyle.tsFace;
  1538.             IF BAND(theMode, doColor) <> 0 THEN
  1539.                 newStyle.tsColor := theStyle.tsColor;
  1540.             IF BAND(theMode, addSize) <> 0 THEN
  1541.                 newStyle.tsSize := newStyle.tsSize + theStyle.tsSize
  1542.             ELSE IF BAND(theMode, doSize) <> 0 THEN
  1543.                 newStyle.tsSize := theStyle.tsSize;
  1544.             END;
  1545.  
  1546.         GetTextStyleFontInfo(newStyle, fInfo);            { Need to get font's height and ascent. }
  1547.  
  1548.         WITH fHTE^^, newStyle, fInfo DO
  1549.             BEGIN
  1550.             txSize := tsSize;
  1551.             txFont := tsFont;
  1552.             txFace := tsFace;
  1553.             fontAscent := ascent;
  1554.             lineHeight := ascent + descent + leading;
  1555.             SetIfColor(tsColor);
  1556.             END;
  1557.         fTextStyle := newStyle;
  1558.         END;
  1559.  
  1560.     IF TRUE                                             { (fStyleType = kWithoutStyle) | (theStart
  1561.                                                          <> theEnd) } THEN
  1562.         BEGIN
  1563.         RecalcText;
  1564.         SynchView(redraw & (fStyleType = kWithStyle));
  1565.         IF redraw & (fStyleType = kWithoutStyle) THEN
  1566.             ForceRedraw;
  1567.         END;
  1568.     fSpecsChanged := TRUE;
  1569.     END;
  1570.  
  1571. {--------------------------------------------------------------------------------------------------}
  1572. {$S TENonRes}
  1573.  
  1574. PROCEDURE TTEView.SetText(theText: Str255);
  1575.  
  1576.     VAR
  1577.         theTextHandle:        Handle;
  1578.  
  1579.     BEGIN
  1580.     IF fHTE <> NIL THEN                                 { If we're replacing text, styles are kaput
  1581.                                                          }
  1582.         BEGIN
  1583.         FailOSErr(PtrToHand(@theText[1], theTextHandle, LENGTH(theText)));
  1584.         StuffText(theTextHandle);
  1585.         END;
  1586.     END;
  1587.  
  1588. {--------------------------------------------------------------------------------------------------}
  1589. {$S TENonRes}
  1590.  
  1591. PROCEDURE TTEView.ShowReverted; OVERRIDE;
  1592.  
  1593.     BEGIN
  1594.     RecalcText;
  1595.     fLastHeight := 0;
  1596.     fLastWidth := 0;
  1597.     INHERITED ShowReverted;
  1598.     END;
  1599.  
  1600. {--------------------------------------------------------------------------------------------------}
  1601. {$S TENonRes}
  1602.  
  1603. FUNCTION TTEView.SpaceForStyles(rangeStart, rangeEnd: LONGINT): BOOLEAN;
  1604.  
  1605.     VAR
  1606.         h:                    Handle;
  1607.  
  1608.     BEGIN
  1609.     h := NewPermHandle(TENumStyles(rangeStart, rangeEnd, fHTE) * SIZEOF(ScrpSTElement) + 2);
  1610.     IF (h = NIL) THEN
  1611.         BEGIN
  1612.         StdAlert(phStylesTooBig);
  1613.         SpaceForStyles := FALSE;
  1614.         END
  1615.     ELSE
  1616.         BEGIN
  1617.         h := DisposeIfHandle(h);                        { Release memory back to the system }
  1618.         SpaceForStyles := TRUE;
  1619.         END;
  1620.     END;
  1621.  
  1622. {--------------------------------------------------------------------------------------------------}
  1623. {$S TENonRes}
  1624.  
  1625. PROCEDURE TTEView.StuffStyles(theStyles: TEStyleHandle;
  1626.                               theElements: STHandle);
  1627.  
  1628.     VAR
  1629.         oldStyles:            TEStyleHandle;
  1630.         oldElements:        STHandle;
  1631.         oldLineHeights:     LHHandle;
  1632.         theNullStyles:        nullSTHandle;
  1633.         theScrpHandle:        STScrpHandle;
  1634.         err:                OSErr;
  1635.  
  1636.     BEGIN
  1637.     IF (fStyleType = kWithStyle) & (fHTE <> NIL) THEN
  1638.         BEGIN
  1639.         oldStyles := GetStylHandle(fHTE);
  1640.  
  1641.         WITH oldStyles^^ DO
  1642.             BEGIN
  1643.             oldElements := styleTab;
  1644.             oldLineHeights := lhTab;
  1645.             theNullStyles := nullStyle;
  1646.             theScrpHandle := nullStyle^^.nullScrap;
  1647.             END;
  1648.  
  1649.         DisposIfHandle(oldElements);
  1650.  
  1651.         WITH theStyles^^ DO
  1652.             BEGIN
  1653.             styleTab := theElements;                    { Replace STElements handle }
  1654.             lhTab := oldLineHeights;                    { Replace line heights table handle }
  1655.             nullStyle := theNullStyles;                 { Replace null style handle }
  1656.             nullStyle^^.nullScrap := theScrpHandle;
  1657.             teRefCon := LONGINT(SELF);                    { store ourselves as the refcon reference }
  1658.             END;
  1659.  
  1660.         { NOTE!! SetStylHandle will dispose of oldStyles for us! }
  1661.         SetStylHandle(theStyles, fHTE);
  1662.  
  1663.         RecalcText;
  1664.         END;
  1665.     END;
  1666.  
  1667. {--------------------------------------------------------------------------------------------------}
  1668. {$S TENonRes}
  1669.  
  1670. PROCEDURE TTEView.StuffText(theText: Handle);
  1671.  
  1672.     VAR
  1673.         styles:             TEStyleHandle;
  1674.         textLength:         LONGINT;
  1675.  
  1676.     BEGIN
  1677.     IF fHTE <> NIL THEN                                 { If we're replacing text, styles are kaput
  1678.                                                          }
  1679.         BEGIN
  1680.         textLength := GetHandleSize(theText);            { Check size of new text }
  1681.         IF textLength > fMaxChars THEN
  1682.             BEGIN
  1683.             {$IFC qDebug}
  1684.             ProgramBreak('Text size exceeds maximum for this view');
  1685.             {$ENDC}
  1686.             Failure(minErr, 0);                         { ??? Assign a message }
  1687.             END;
  1688.  
  1689.         IF fSavedTEHandle <> theText THEN
  1690.             BEGIN
  1691.             fSavedTEHandle := DisposeIfHandle(fSavedTEHandle); { …we have no choice but to dispose
  1692.                                                                 it }
  1693.             fSavedTEHandle := fHTE^^.hText;             { Save existing handle }
  1694.             END;
  1695.         WITH fHTE^^ DO
  1696.             BEGIN
  1697.             hText := theText;                            { Install new handle }
  1698.             fText := theText;                            { Make a local copy, too }
  1699.             teLength := textLength;                     { Tell TE how long we are }
  1700.             END;
  1701.  
  1702.         IF fStyleType = kWithStyle THEN                 { Fix for styled TE. Yuk. }
  1703.             BEGIN
  1704.             styles := GetStylHandle(fHTE);
  1705.             styles^^.runs[1].startChar := SUCC(fHTE^^.teLength);
  1706.             styles^^.nRuns := 1;
  1707.             styles^^.nStyles := 1;
  1708.             { Thanks to map }
  1709.             END;
  1710.         END;
  1711.     END;
  1712.  
  1713. {--------------------------------------------------------------------------------------------------}
  1714. {$S TENonRes}
  1715.  
  1716. PROCEDURE TTEView.StuffTERects(newTERect: Rect);
  1717.  
  1718.     VAR
  1719.         aFontInfo:            FontInfo;
  1720.  
  1721.     BEGIN
  1722.  
  1723.     GetFontInfo(aFontInfo);
  1724.     WITH newTERect DO
  1725.         right := MAX(right, left + aFontInfo.widMax);
  1726.     WITH fHTE^^ DO
  1727.         BEGIN
  1728.         destRect := newTERect;
  1729.         viewRect := newTERect;
  1730.         END;
  1731.     END;
  1732.  
  1733. {--------------------------------------------------------------------------------------------------}
  1734. {$S TERes}
  1735.  
  1736. PROCEDURE TTEView.SynchView(redraw: BOOLEAN);
  1737.     CONST
  1738.         kInsertionBarWidth = 1;                        { We all _KNOW_ an insertion bar is one
  1739.                                                     pixel wide right? }
  1740.  
  1741.     VAR
  1742.         aRect:                Rect;
  1743.         theHeight:            LONGINT;
  1744.         theWidth:            LONGINT;
  1745.         doRealWidth:        BOOLEAN;
  1746.  
  1747.     BEGIN
  1748.     theHeight := CalcRealHeight;
  1749.  
  1750.     doRealWidth := (fSizeDeterminer[h] = sizeVariable) & NOT fStyleType & NOT fAutoWrap;
  1751.     IF doRealWidth THEN
  1752.         theWidth := CalcRealWidth + kInsertionBarWidth * 2;
  1753.  
  1754.     IF (fLastHeight <> theHeight) | (doRealWidth & (fLastWidth <> theWidth)) THEN
  1755.         BEGIN
  1756.         IF doRealWidth THEN
  1757.             fLastWidth := theWidth; { Width is expensive to calculate.  Cache for CalcMinSize }
  1758.  
  1759.         AdjustSize;                                     { may need to grow view }
  1760.         fLastHeight := theHeight;                        { Remember new height value }
  1761.         END;
  1762.  
  1763.     IF redraw & Focus THEN
  1764.   { First, make sure selection is visible (this conveniently focuses). Then,
  1765.    repair any extra feedback which TextEdit may have mashed. }
  1766.         BEGIN
  1767.         ScrollSelectionIntoView;
  1768.         DoHighlightSelection(hlOff, fHLDesired);
  1769.         IF fPrintHandler <> NIL THEN
  1770.             BEGIN
  1771.             GetVisibleRect(aRect);
  1772.             DoDrawPrintFeedback(aRect);
  1773.             END;
  1774.         END;
  1775.     END;
  1776.  
  1777. {--------------------------------------------------------------------------------------------------}
  1778. {$S TENonRes}
  1779.  
  1780. PROCEDURE TTEView.WriteToDeskScrap; OVERRIDE;
  1781.  
  1782.     VAR
  1783.         aHandle:            Handle;
  1784.  
  1785.     BEGIN
  1786.     FailOSErr(PutDeskScrapData('TEXT', fText));
  1787.  
  1788.     IF (fStyleType = kWithStyle) & SpaceForStyles(0, MAXINT) THEN
  1789.         BEGIN
  1790.         SetSelect(0, MAXINT, fHTE);
  1791.         aHandle := Handle(GetStylScrap(fHTE));
  1792.         FailNIL(aHandle);
  1793.         FailOSErr(PutDeskScrapData('styl', aHandle));
  1794.         END;
  1795.     END;
  1796.  
  1797. {--------------------------------------------------------------------------------------------------}
  1798. {$S TERes}
  1799.  
  1800. PROCEDURE TTEView.ViewEnable(state, redraw: BOOLEAN);
  1801.  
  1802.     BEGIN
  1803.     IF state & (fIdleFreq = kMaxIdleTime) THEN
  1804.         SetIdleFreq(0);                                 { Get correct idle set ASAP }
  1805.  
  1806.     INHERITED ViewEnable(state, redraw);
  1807.     END;
  1808.  
  1809. {--------------------------------------------------------------------------------------------------}
  1810. {$S TEDebug}
  1811.  
  1812. PROCEDURE TTEView.IdentifySoftware; OVERRIDE;
  1813.  
  1814.     BEGIN
  1815.     WRITELN('UTEView of 14 Feb 90 (Valentine''s Day), Compiled on ', COMPDATE, ' @ ', COMPTIME);
  1816.     INHERITED IdentifySoftware;
  1817.     END;
  1818.  
  1819. {--------------------------------------------------------------------------------------------------}
  1820. {$S TEFields}
  1821.  
  1822. PROCEDURE TTEView.Fields(PROCEDURE DoToField(fieldName: Str255;
  1823.                                              fieldAddr: Ptr;
  1824.                                              fieldType: INTEGER)); OVERRIDE;
  1825.  
  1826.     BEGIN
  1827.     DoToField('TTEView', NIL, bClass);
  1828.     DoToField('fHTE', @fHTE, bTEHandle);
  1829.     DoToField('fText', @fText, bHandle);
  1830.     DoToField('fSavedTEHandle', @fSavedTEHandle, bHandle);
  1831.     DoToField('fInset', @fInset, bRect);
  1832.     DoToField('fKeyCmdNumber', @fKeyCmdNumber, bCmdNumber);
  1833.     DoToField('fMaxChars', @fMaxChars, bInteger);
  1834.     DoToField('fLastHeight', @fLastHeight, bLongInt);
  1835.     DoToField('fLastWidth', @fLastWidth, bLongInt);
  1836.     DoToField('fTypingCommand', @fTypingCommand, bObject);
  1837.     {$Push} {$H-}
  1838.     TextStyleFields('fTextStyle', fTextStyle, DoToField);
  1839.     {$Pop}
  1840.     DoToField('fJustification', @fJustification, bInteger);
  1841.     DoToField('fAcceptsChanges', @fAcceptsChanges, bBoolean);
  1842.     DoToField('fStyleType', @fStyleType, bBoolean);
  1843.     DoToField('fAutoWrap', @fAutoWrap, bBoolean);
  1844.     DoToField('fFreeText', @fFreeText, bBoolean);
  1845.     DoToField('fSpecsChanged', @fSpecsChanged, bBoolean);
  1846.     DoToField('fLastLine', @fLastLine, bInteger);
  1847.     DoToField('fLastPageBreak', @fLastPageBreak, bInteger);
  1848.     DoToField('fControlChars', @fControlChars, bHexLongInt);
  1849.     DoToField('fMinAhead', @fMinAhead, bInteger);
  1850.  
  1851.     INHERITED Fields(DoToField);
  1852.     END;
  1853.